package com.alm.handle.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alm.common.core.domain.AjaxResult;
import com.alm.common.utils.StringUtils;
import com.alm.entity.PasingByteModel;
import com.alm.handle.core.domain.entity.AlmDevException;
import com.alm.handle.core.domain.entity.rq.DevExEditRq;
import com.alm.handle.core.domain.entity.rq.DevExQueryRq;
import com.alm.handle.core.domain.entity.vo.DevExVo;
import com.alm.handle.mapper.SysDevExceptionMapper;
import com.alm.handle.service.ISysDevExceptionService;
import com.alm.handle.util.ByteUtils;
import com.alm.handle.util.DataUtils;
import com.alm.handle.util.RedisUtil;
import com.alm.handle.util.SoketEleKey;
import com.alm.handle.websocket.WebsocketServer;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.alm.common.constant.Constants.EX_MAP;
import static com.alm.common.utils.PageUtils.startPage;

/**
 * 设备异常信息服务实现类
 *
 * @author: 詹泽峰
 * @date: 2024/7/24 17:21
 */
@Slf4j
@Service
public class SysDevExceptionServiceImpl implements ISysDevExceptionService {

    @Resource
    private SysDevExceptionMapper sysDevExceptionMapper;
    @Resource
    private RedisUtil redisUtil;

    /**
     * 更新异常信息
     *
     * @param header 数据封装对象
     * @author: 詹泽峰
     * @date: 2024/7/30 15:17
     */
    @Override
    public void updateDevExceptionInfo(PasingByteModel.Header header) throws IOException {
        AlmDevException exDTO = new AlmDevException();
        //data解析
        String data = ByteUtils.arrayToString(header.getIntData(), 0, header.getIntData().size());
        String exInfo = DataUtils.parseDevExData(data.toUpperCase());
        //若异常信息获取为空，则不处理
        if (StringUtils.isBlank(exInfo)) {
            return;
        }
        //设置异常信息对象
        exDTO.setMac(header.getDvcId());
        exDTO.setDevType(header.getDvcType());
        exDTO.setDevExType(EX_MAP.get(exInfo));
        exDTO.setDevExInfo(exInfo);
        exDTO.setViewed(false);
        exDTO.setOccurTime(System.currentTimeMillis() / 1000);
        //封装json
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonData = new JSONObject();
        jsonData.put("msg", "插座：" + exDTO.getMac() + "发生异常：" + exDTO.getDevExInfo());
        jsonObject.put("data", jsonData);
        jsonObject.put("msgType", "dev_ex");
        //发送异常信息通知前端
        WebsocketServer.sendInfo(jsonObject.toJSONString(), "alm_ex_alert");
        List<AlmDevException> almDevExceptionList;
        //存入缓存
        if (redisUtil.hasKey(SoketEleKey.EXCEPTION)) {
            almDevExceptionList = JSON.parseArray(JSON.toJSON(redisUtil.get(SoketEleKey.EXCEPTION)).toString(),
                    AlmDevException.class);
        } else {
            almDevExceptionList = new ArrayList<>();
        }
        almDevExceptionList.add(exDTO);
        redisUtil.set(SoketEleKey.EXCEPTION, JSON.toJSONString(almDevExceptionList), 86400);
        //存入数据库
        sysDevExceptionMapper.insert(exDTO);
    }

    /**
     * 返回异常统计列表
     *
     * @return com.alm.common.core.domain.AjaxResult
     * @author: 詹泽峰
     * @date: 2024/7/30 14:17
     */
    @Override
    public AjaxResult getDevExList() {
        String key = SoketEleKey.EXCEPTION;
        List<AlmDevException> almDevExceptionList;
        //若缓存有记录则从缓存中获取，若无则从数据库获取
        if (!redisUtil.hasKey(key)) {
            QueryWrapper<AlmDevException> queryWrapper = new QueryWrapper<>();
            almDevExceptionList = sysDevExceptionMapper.selectList(queryWrapper);
            redisUtil.set(SoketEleKey.EXCEPTION, JSON.toJSONString(almDevExceptionList), 86400);
        } else {
            String devExStr = JSON.toJSON(redisUtil.get(key)).toString();
            almDevExceptionList = JSON.parseArray(devExStr, AlmDevException.class);
        }
        List<DevExVo> devExVoList = almDevExceptionList.stream().map(obj -> {
            DevExVo vo = new DevExVo();
            BeanUtils.copyProperties(obj, vo);
            return vo;
        }).collect(Collectors.toList());
        return AjaxResult.success("获取成功", devExVoList);
    }

    /**
     * 查询异常列表（带条件）
     *
     * @param rq 查询条件
     * @return java.util.List<com.alm.handle.core.domain.entity.vo.DevExVo> 异常列表
     * @author: 詹泽峰
     * @date: 2024/8/5 14:34
     */
    @Override
    public List<AlmDevException> getListByRq(DevExQueryRq rq) {
        //若依框架分页问题导致不能对mapper查出的数据做二次处理，临时调整
        List<AlmDevException> almDevExceptionList = sysDevExceptionMapper.getExListByRq(rq);
        startPage(rq.getPageNum(), rq.getPageSize());
//        List<DevExVo> devExVoList = almDevExceptionList.stream().map(obj -> {
//            DevExVo vo = new DevExVo();
//            BeanUtils.copyProperties(obj, vo);
//            return vo;
//        }).collect(Collectors.toList());
        return almDevExceptionList;
    }

    /**
     * 返回该mac地址对应设备的未查看过的异常列表
     *
     * @param rq 前端给的查询条件
     * @return com.alm.common.core.domain.AjaxResult
     * @author: 詹泽峰
     * @date: 2024/7/30 15:17
     */
    @Override
    public AjaxResult getDevExNotViewedByMac(DevExQueryRq rq) {
        LambdaQueryWrapper<AlmDevException> queryWrapper = new LambdaQueryWrapper<AlmDevException>()
                .eq(AlmDevException::getMac, rq.getMac())
                .eq(AlmDevException::getIsViewed, false);
        List<AlmDevException> almDevExceptionList = sysDevExceptionMapper.selectList(queryWrapper);
        return AjaxResult.success("获取成功", almDevExceptionList);
    }

    /**
     * 修改未读状态为已读状态
     *
     * @param rq 前端给的查询条件
     * @return int
     * @author: 詹泽峰
     * @date: 2024/8/1 10:45
     */
    @Override
    public int updateDevExIsViewed(DevExEditRq rq) {
        UpdateWrapper<AlmDevException> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", rq.getId()).set("is_viewed", 1);
        return sysDevExceptionMapper.update(null, updateWrapper);
    }
}
